<?php

namespace Modules\Core\Models;

use App\Models\BaseModel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Nwidart\Modules\Facades\Module;
use Stancl\Tenancy\Database\Concerns\BelongsToTenant;

class Option extends BaseModel
{
    use BelongsToTenant;

    public $timestamps = false;
    protected $oid = '';
    protected $cache;

    public $table = 'core_options';

    /**
     * The attributes that are mass assignable.
     *
     * @var [type]
     */
    protected $fillable = ['key', 'value', 'oid'];

    protected static function boot()
    {
        parent::boot();
        // 清除缓存
        $cache = (new self())->_getCacheObj();
        static::created(function ($model) use($cache) {
            $cache->flush();
        });
        static::updated(function ($model) use($cache) {
            $cache->flush();
        });
        static::deleted(function ($model) use($cache) {
            $cache->flush();
        });
    }

    /**
     * Determine if the given option value exists.
     *
     * @param  string  $key
     * @return bool
     */
    public function exists($key)
    {
        return self::where('key', $key)->exists();
    }

    private function _getCacheObj()
    {
        if(!$this->cache) {
            $this->cache = app('cache');
            if(in_array($this->cache->getDefaultDriver(), ['redis', 'memcached'])) {
                $this->cache = $this->cache->tags('option');
            }
        }
        return $this->cache;
    }

    private function _getCacheKey($key)
    {
        return 'option_'.($this->_getTenant() ?? 1).'_'.$key;
    }

    private function _getTenant()
    {
        return tenant('id') ?? tenant_from_url();
    }

    /**
     * Get the specified option value.
     *
     * @param  string  $key
     * @param  mixed   $default
     * @return mixed
     */
    public function get($key, $default = null)
    {
        $_cacheKey = $this->_getCacheKey($key);

        $cache = $this->_getCacheObj();
        $val = $cache->get($_cacheKey);

        if(!$val) {
            if ($option = self::where('key', $key)->where('tenant_id', $this->_getTenant())->first()) {
                $val = $option->value;
            }
            if(is_null($val)) {
                 // 数据库不存在取默认值
                 $val = $default;
                // 数据库不存在,也无默认值时取配置文件
                if(!$val) {
                    $_config_options = collect();
                    foreach(Module::getOrdered() as $module){
                        $_config = config($module->getAlias().'.options') ?? [];
                        $_config_options = $_config_options->merge($_config);
                    }
                    $val = $_config_options->pluck('default', 'name')->get($key);
                    // 解析:tenant_id
                    if(Str::contains($val, ':tenant_id')) {
                        $val = Str::replaceFirst(':tenant_id', tenant('id'), $val);
                    }
                }
            }
            $cache->set($_cacheKey, $val);
        }
        return $val;
    }

    /**
     * Set a given option value.
     *
     * @param  array|string  $key
     * @param  mixed   $value
     * @return void
     */
    public function set($key, $value = null)
    {
        $keys = is_array($key) ? $key : [$key => $value];

        foreach ($keys as $key => $value) {
            self::updateOrCreate(
                ['key' => $key, 'tenant_id' => $this->_getTenant()],
                ['value' => $value]
            );
        }

        // @todo: return the option
    }

    /**
     * Remove/delete the specified option value.
     *
     * @param  string  $key
     * @return bool
     */
    public function remove($key)
    {
        return (bool) self::where('key', $key)->where('tenant_id', $this->_getTenant())->delete();
    }
}
